package indi.mozping.controller;

import com.alibaba.fastjson.JSONObject;
import indi.mozping.random.RandomUtil;
import indi.mozping.service.AddService;
import indi.mozping.utils.Util;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;

/**
 * @author by mozping
 * @Classname InsertTestController
 * @Description 测试写入性能
 * @Date 2019/5/16 10:02
 */
@RestController
@RequestMapping("/test")
public class InsertTestController {

    private static final int THREAD_NUM = 1;
    private static final Logger LOG = LoggerFactory.getLogger(AddController.class);
    public static CountDownLatch latch;

    @Autowired
    AddService addService;

    @PostMapping("/add")
    public JSONObject testAdd(@RequestBody JSONObject param) throws Exception {

        int threadNum = THREAD_NUM;
        if (param.getIntValue("threadNum") > 0) {
            threadNum = param.getIntValue("threadNum");
        }
        latch = new CountDownLatch(threadNum);

        int recordNum = 10000;
        if (param.getIntValue("recordNum") > 0) {
            recordNum = param.getIntValue("recordNum") * 10000;
        }

        int batchNum = 1000;
        if (param.getIntValue("batchNum") > 0) {
            batchNum = param.getIntValue("batchNum");
        }

        String tableName = "multobj";
        if (!(param.getString("tableName") == null)) {
            tableName = param.getString("tableName");
        }

        String size = "small";
        if (!(param.getString("size") == null) && "big".equalsIgnoreCase(param.getString("size"))) {
            size = "big";
        }

        long countBefore = addService.count(tableName);
        LOG.info("Begin testAdd...,the docs in table " + tableName + " is : " + countBefore);

        int numPerThread = recordNum / threadNum;

        long begin = System.currentTimeMillis();
        for (int i = 1; i <= threadNum; i++) {
            new MyThread(numPerThread, batchNum, tableName, size, addService).start();
        }
        latch.await();
        JSONObject json = new JSONObject();
        long time = System.currentTimeMillis() - begin;
        long speed = (recordNum * 1000) / time;
        int sizeKb = "big".equalsIgnoreCase(size) ? 20 : 1;
        json.put("time", time + " ms");
        json.put("speed", speed + " /S");
        StringBuilder sb = new StringBuilder();

        JSONObject detail = new JSONObject();
        detail.put("执行插入线程数是: ", threadNum);
        detail.put("插入总数是: ", recordNum / 10000 + "万");
        detail.put("插入耗时是: ", time + "ms;");
        detail.put("插入速度是: ", speed + "/S;");
        detail.put("每次插入的批次记录数是: ", batchNum);
        detail.put("插入的记录大小是: ", sizeKb + "kb;");
        detail.put("插入前数据库记录数量是: ", countBefore);
        json.put("detail", detail);
        json.put("response", "新增:" + recordNum + "条数据成功!");
        LOG.info("Result: " + json);
        return json;
    }


    class MyThread extends Thread {

        private int total;
        private int batchNum;
        private String tableName;
        private String size;
        private AddService addService;

        public MyThread(int total, int batchNum, String tableName, String size, AddService addService) {
            this.total = total;
            this.batchNum = batchNum;
            this.tableName = tableName;
            this.size = size;
            this.addService = addService;
        }

        ArrayList<Document> arrayList = new ArrayList<>(1000);

        @Override
        public void run() {
            int loop = total / batchNum;

            for (int j = 1; j <= loop; j++) {
                for (int i = 1; i <= batchNum; i++) {
                    Document doc;
                    if ("big".equalsIgnoreCase(size)) {
                        doc = RandomUtil.getDocument20kb();
                    } else {
                        doc = RandomUtil.getDocument1kb();
                    }
                    doc.put("targetType", RandomUtil.targetType());
                    doc.put("time", Util.getTimeBetween3Month());
                    doc.put("sourceId", "abcdefg");
                    arrayList.add(doc);
                }
                try {
                    addService.add(arrayList, tableName);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    arrayList.clear();
                }
            }
            latch.countDown();
            LOG.info("线程" + Thread.currentThread().getName() + "新增 " + total + " 条数据成功...");
        }
    }


}